////////////////////////////////////////////////////////////////////
//
// NO_Object.h header for the NO_Object class.
//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#ifndef NO_Object_H
#define NO_Object_H

//////////////////////////////////////////////////////////////////////////
#include "NO_Includes.h"
#include "NO_Value.h"

//////////////////////////////////////////////////////////////////////////
class NO_Type;
class NO_TypeList;
class NO_ObjectList;
class NO_IFunction;

//////////////////////////////////////////////////////////////////////////
// class NO_Object iterator definition
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_ObjectIter
{
public:	
	//////////////////////////////////////////////////////////////////////////
	NO_ObjectIter (NO_Value::ObjectSetIter& iter);
	
	//////////////////////////////////////////////////////////////////////////
	bool			operator!=	(const NO_ObjectIter& rhs) const;
	bool			operator==	(const NO_ObjectIter& rhs) const;
	NO_Object		operator*	(void);
	NO_ObjectIter	operator++	(int);
	NO_ObjectIter	operator++	(void);

protected: 
	//////////////////////////////////////////////////////////////////////////
	friend class NO_Object;
	
	//////////////////////////////////////////////////////////////////////////
	NO_Value::ObjectSetIter iter;
};

//////////////////////////////////////////////////////////////////////////
// class NO_Object definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_Object  
{
public:
	//////////////////////////////////////////////////////////////////////////
	typedef NO_Value								Data;
	typedef fastdelegate::FastDelegate1<NO_Object&> ObjectDelegate;
	typedef NO_IDVector<ObjectDelegate>				ObjectDelegates;
	typedef ObjectDelegates::iterator				ObjectDelegateIter;

	//////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_Object(void);
	NO_Object(const NO_Object& rhs);
	NO_Object(const NO_Type& type,		NO_UInt32 num = 1);
	NO_Object(const NO_Int8* typeName,	NO_UInt32 num = 1);
	NO_Object(const NO_Type& type,		const NO_Int8* name, NO_UInt32 num = 1);
	NO_Object(const NO_Int8* typeName,	const NO_Int8* name, NO_UInt32 num = 1);

	//////////////////////////////////////////////////////////////////////
	virtual ~NO_Object();
	
	//////////////////////////////////////////////////////////////////////
	NO_Object& operator= (const NO_Object& rhs);
	
	//////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	static NO_ObjectIter getBegin	(void);
	static NO_ObjectIter getEnd		(void);
	static NO_ObjectIter getNext	(NO_ObjectIter& iter);
	static NO_ObjectIter find		(NO_UInt32 id);
	
	//////////////////////////////////////////////////////////////////////
	virtual NO_UInt32		getID(void)			const;
	virtual NO_UInt32		getNum(void)		const;
	virtual std::string		getName(void)		const;
	virtual NO_Type const &	getType(void)		const;
	virtual NO_Object		getMaster(void)		const;
	virtual NO_Type const &	getDynamicType(void)const;
	virtual NO_Boolean		getInitialized(void)const;
	
	//////////////////////////////////////////////////////////////////////////
	// use
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	virtual NO_Object	cast(const NO_Type&)		const;
	virtual NO_Boolean	isKindOf(const NO_Type&)	const;

	//////////////////////////////////////////////////////////////////////
	virtual NO_Object base	(const NO_Int8* name)	const;
	virtual NO_Object base	(const NO_IBase& obj)	const;
	virtual NO_Object member(const NO_Int8* name)	const;
	virtual NO_Object member(const NO_IMember& obj)	const;

	//////////////////////////////////////////////////////////////////////
	virtual NO_Object copy			(void)			const;
	virtual NO_Object element		(NO_UInt32 num)	const;
	virtual NO_Object reference		(void)			const;
	virtual NO_Object dereference	(void)			const;

	//////////////////////////////////////////////////////////////////////
	virtual NO_IFunction const & function (NO_UInt32 id);
	virtual NO_IFunction const & function (const NO_Int8*, NO_TypeList& parameter);

	//////////////////////////////////////////////////////////////////////
	virtual void call(NO_UInt32 id, NO_Object& result = NO_Object::empty);
	virtual void call(NO_UInt32 id, NO_ObjectList& parameter, NO_Object& result = NO_Object::empty);
	virtual void call(const NO_Int8* name, NO_Object& result = NO_Object::empty);
	virtual void call(const NO_Int8* name, NO_ObjectList& parameter, NO_Object& result = NO_Object::empty);

	//////////////////////////////////////////////////////////////////////////
	virtual NO_OArchive&	output (NO_OArchive& a);
	virtual NO_IArchive&	input  (NO_IArchive& a);
	
	//////////////////////////////////////////////////////////////////////
	// operators
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
			   operator NO_Boolean	(void)				const;
	NO_Boolean operator !			(void)				const;
	NO_Boolean operator ==			(const NO_Object&)	const;
	NO_Boolean operator !=			(const NO_Object&)	const;

	//////////////////////////////////////////////////////////////////////////
	static NO_Object&		empty;
	static ObjectDelegates	onConstruction; 
	static ObjectDelegates	onDestruction; 

protected:
	//////////////////////////////////////////////////////////////////////////
	friend struct NO_PrivateHelper;
	friend class NO_EditWidget;
	friend class NO_IArchive;
	friend class NO_ObjectIter;

	//////////////////////////////////////////////////////////////////////////
	NO_Object(NO_Value* rhs);

	//////////////////////////////////////////////////////////////////////////
	NO_Object&	assign		(NO_Value* rhs);
	NO_Object&	assign		(const NO_Object& rhs);
	void		initialize	(const NO_Type&, const NO_Int8*, NO_UInt32);
	virtual void release	(void);
	
	//////////////////////////////////////////////////////////////////////////
	NO_Value* data;
};

//////////////////////////////////////////////////////////////////////////
// class NO_EmptyObject definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_EmptyObject : public NO_Object
{
public:
	//////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_EmptyObject(void);
	
	//////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////
	virtual NO_UInt32		getID(void)			const;
	virtual NO_UInt32		getNum(void)		const;
	virtual std::string		getName(void)		const;
	virtual const NO_Type&	getType(void)		const;
	virtual const NO_Type&	getDynamicType(void)const;
	virtual NO_Boolean		getInitialized(void)const;

	//////////////////////////////////////////////////////////////////////////
	static NO_EmptyObject empty;
};

//////////////////////////////////////////////////////////////////////////
template<class T> class NO_ContainerFriendHelper;

//////////////////////////////////////////////////////////////////////////
// class NO_TypeObject definition
//////////////////////////////////////////////////////////////////////////
template<class T>
class NO_TypeObject : public NO_Object
{
public:
	//////////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	virtual ~NO_TypeObject()				{}
	NO_TypeObject():NO_Object()				{assign(NO_TypeID<T>::type().findConstructor(0)->construct(1,NO_ObjectList::empty));}
	NO_TypeObject(T const & v):NO_Object()	{assign(new NO_CopyValue<T>(v));}

//private:
	//////////////////////////////////////////////////////////////////////////
	// friends
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	friend class NO_OArchive;
	friend class NO_ContainerFriendHelper<T>;

	//////////////////////////////////////////////////////////////////////////
	NO_TypeObject(T* v):NO_Object()	{assign(new NO_ReferenceValue<T>(v,0));}
};

#endif 
